import copy
import datetime
import os
import inspect
import pickle
import random

def rand(a, b):
  return(b - a)*random.random() + a

def filename_at_current_path(filename):
  return "%s/%s" % (os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))), filename)

def generate_random_weights():
  input_weights = []
  for i in range(5):
    input_weights.append([])
    for j in range(7):
      input_weights[i].append(rand(-0.2,0.2))

  output_weights = []
  for i in range(7):
    output_weights.append([])
    for j in range(8):
      output_weights[i].append(rand(-2.0, 2.0))

  return (input_weights, output_weights)

def write_weights(filename, my_id, parent_id, input_weights, output_weights):
  nn_info = {}
  nn_info["input_weights"] = input_weights
  nn_info["output_weights"] = output_weights
  nn_info["id"] = my_id
  nn_info["parent"] = parent_id
  nn_info["create time"] = datetime.datetime.now().strftime("%Y/%m/%d %H:%M")
  pickle.dump(nn_info, open(filename_at_current_path(filename), 'wb'))

def mutate_weights(nn_info):
  input_weights = copy.deepcopy(nn_info["input_weights"])
  for row in range(len(input_weights)):
    for col in range(len(input_weights[0])):
      input_weights[row][col] += random.gauss(0.0, 0.1)
         
  output_weights = copy.deepcopy(nn_info["output_weights"])
  for row in range(len(output_weights)):
    for col in range(len(output_weights[0])):
      output_weights[row][col] += random.gauss(0.0, 0.4)
  return (input_weights, output_weights)

def generate_initial_weights(num_weights, evolution_file):
  for i in range(num_weights):
    input_weights, output_weights = generate_random_weights()
    write_weights("NN%d.dump" % i, i, "", input_weights, output_weights)
  print i
  evolution_data = {}
  evolution_data["next_id"] = i + 1
  pickle.dump(evolution_data, open(filename_at_current_path(evolution_file), 'wb')) 

def mutate_population(files_to_keep, files_to_die, evolution_file):
  evolution_data = pickle.load(open(filename_at_current_path(evolution_file)))
  next_id = evolution_data["next_id"]
  assert(len(files_to_keep) == len(files_to_die))
  parent_child_pairs = []
  for i in range(len(files_to_keep)):
    nn = pickle.load(open(filename_at_current_path(files_to_keep[i])))
    input_weights, output_weights = mutate_weights(nn)
    write_weights(files_to_die[i], next_id, nn["id"], input_weights, output_weights)
    parent_child_pairs.append((nn["id"], next_id))
    next_id += 1
  evolution_data["next_id"] = next_id
  try:
    evolution_data["parent_child_pairs"].append(parent_child_pairs)
  except KeyError:
    evolution_data["parent_child_pairs"] = [parent_child_pairs]
  pickle.dump(evolution_data, open(filename_at_current_path(evolution_file), 'wb'))

def debug_print(nn_files, evolution_file):
  for nn in nn_files:
    print "file: %s" % nn
    print pickle.load(open(filename_at_current_path(nn)))
  print "evolution file:"
  print pickle.load(open(filename_at_current_path(evolution_file)))
  

if __name__ == "__main__":
  # generate_initial_weights(4, "evolution.dump")
  debug_print(["NN%d.dump" % i for i in range(4)], "evolution.dump")
